package com.example.shiro.common.exception;


import com.example.shiro.common.response.CommonCode;
import com.example.shiro.common.response.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * @auther 严旭平
 * @date 2020/4/818:45
 * @Description 全局异常处理类
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 未授权请求拦截
     * @param e
     * @return
     */
    @ExceptionHandler(UnauthorizedException.class)
    public R handleUnauthorizedException( UnauthorizedException e ){
        return R.setResult( CommonCode.UNAUTHORIZED );
    }


    /**
     * 文件过大异常捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R handleSizeLimitExceededException(MaxUploadSizeExceededException e) {
        log.info("文件上传异常" + e.getMessage());
        log.info("最大上传大小为" + e.getMaxUploadSize());
        return R.error().data("message", e.getMessage()).msg("文件过大,请控制在" + e.getMaxUploadSize() + "以内");
    }


    /**
     * 处理数据库异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MyBatisSystemException.class)
    public R handleMyBatisSystemException(MyBatisSystemException e) {
        log.info("出现了MyBatisSystemException" + e.getMessage());
        return R.setResult(CommonCode.INTERNAL_SERVER_ERROR);
    }

    /**
     * JSON序列花异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        log.info("出现了HttpMessageNotReadableException");
        log.error(e.getMessage());
        return R.setResult(CommonCode.JSON_PARSE_ERROR);
    }

    /**
     * 处理对象参数校验异常
     *
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.info("出现了MethodArgumentNotValidException");
        log.error(e.getMessage());
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            return R.setResult(CommonCode.PARAM_ERROR).data("error", fieldError.getDefaultMessage());
        }
        return R.setResult(CommonCode.PARAM_ERROR);
    }

    /**
     * 参数验证不通过
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public R handleConstraintViolationException(ConstraintViolationException e) {
        log.info("出现了ConstraintViolationException" + e.getMessage());
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            return R.setResult(CommonCode.PARAM_ERROR).data("errors", constraintViolation.getPropertyPath().toString() + "验证异常," + constraintViolation.getMessageTemplate());
        }
        return R.setResult(CommonCode.PARAM_ERROR);

    }

    /**
     * 遗忘了请求参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public R handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        log.info("出现了MissingServletRequestParameterException");
        log.error(e.getMessage());
        return R.setResult(CommonCode.PARAM_ERROR).data("errors", e.getParameterName() + "不能为空");
    }

    /**
     * 是实体类与数据数属性对应异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(InvalidDataAccessApiUsageException.class)
    public R handleInvalidDataAccessApiUsageException(InvalidDataAccessApiUsageException e) {
        log.info("出现了InvalidDataAccessApiUsageException");
        log.error(e.getMessage());
        return R.setResult(CommonCode.INTERNAL_SERVER_ERROR);
    }

    /**
     * 处理自定义异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MyException.class)
    public R handleMyException(MyException e) {
        return R.error().code(e.getCode()).msg(e.getMessage());
    }

    /**
     * 统一处理其它异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public R error(Exception e) {
        e.printStackTrace();
        log.info("出现了ExceptionHandler" + e.getMessage());
        return R.setResult(CommonCode.INTERNAL_SERVER_ERROR);
    }

}
